package com.yhh;

import com.yhh.Entity.Command;
import com.yhh.Entity.HandlerCommand;
import com.yhh.Entity.MyFile;
import com.yhh.Exceptions.*;

import java.io.*;
import java.net.Socket;
import java.util.Date;
import java.util.Map;

import static com.yhh.Pipeline.directory;
import static com.yhh.Pipeline.pipeline;

class RecvCommand extends Command implements HandlerCommand {
    private static final String c = "recv";


    private FileInputStream fis;

    private DataOutputStream dos;

    protected RecvCommand(Socket socket) {
        super(socket);
        command.add("recv");
        command.add("-m");
        command.add("-r");
    }

    @Override
    public void handlerParameter(Map<String, String> args) throws InstructionException, NonInstructionException {
        if (args.get("-m") == null || args.get("-m").length() != 10) {
            throw new InstructionException("-m参数有误", c);
        }
    }

    @Override
    public boolean check(Map<String, String> args) throws InstructionException, NonInstructionException {
        checkParameter(args);
        handlerParameter(args);
        return true;
    }

    @Override
    public void handlerCommand(Map<String, String> args) throws InstructionException, NonInstructionException {
        if (args.get("-r") != null) {
            //重传逻辑
            handlerResend();
        }
        String m = args.get("-m");
        MyFile file = pipeline.get(m);
        System.out.println(file);
        try {
            handlerRecv(file);
        } catch (WrongKeyException e) {
            sendMsg("错误的key");
        } catch (CountsZeroException e) {
            sendMsg("文件已删除");
        } catch (FileExpiredException e) {
            sendMsg("文件已过期");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //获取客户端的回传
        String resp = recvMsg();
        if ("success".equals(resp)) {
            //文件接收的善后工作
            file.setCounts(file.getCounts() - 1);
            file.setUpdate_time(new Date());
            file.setLastIp(socket.getInetAddress().toString());
            ServerThread.save();
        }
    }

    //接受函数
    public void handlerRecv(MyFile file) throws WrongKeyException, CountsZeroException, FileExpiredException, IOException {

        if (file == null) {
            throw new WrongKeyException();
        } else if (file.getCounts() <= 0) {
            throw new CountsZeroException();
        } else if (file.isExpired()) {
            throw new FileExpiredException();
        }
        File _file = new File(directory.getAbsolutePath() + File.separatorChar + file.getFilePath());
        if (!_file.exists()) {
            throw new FileNotFoundException();
        }
        sendMsg("ready");
        synchronized (_file) {
            fis = new FileInputStream(_file);
            dos = new DataOutputStream(socket.getOutputStream());
            // 文件名和长度
            dos.writeUTF(_file.getName());
            dos.flush();
            dos.writeLong(_file.length());
            dos.flush();
            System.out.println("开始发送");
            byte[] bytes = new byte[1024];
            int length = 0;
            while ((length = fis.read(bytes, 0, bytes.length)) != -1) {
                dos.write(bytes, 0, length);
                dos.flush();
            }
            System.out.println("文件传输完毕");
            if (fis != null) fis.close();

        }
    }

    public void handlerResend() {

        sendMsg("ready");
        try {
            //接受一个key和一个客户端已存参数
            //获取客户端的key
            String key = recvMsg();
            //获取客户端的文件长度
            String fLength = recvMsg();
            //获取到文件类
            MyFile file = pipeline.get(key);
            if (file == null) {
                throw new FileNotFoundException();
            }
            sendMsg("ready");
            File _file = new File(directory.getAbsolutePath() + File.separatorChar + file.getFilePath());

            DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
            FileInputStream fis = new FileInputStream(_file);
            //跳到指定字节
            fis.skip(Integer.parseInt(fLength));

            dos.writeLong(_file.length());
            dos.flush();

            System.out.println("开始发送");
            byte[] bytes = new byte[1024];
            int length;
            while ((length = fis.read(bytes, 0, bytes.length)) != -1) {
                dos.write(bytes, 0, length);
                dos.flush();
            }
            System.out.println("文件传输完毕");
            //阻塞获取客户端传来的信息，确保文件传输成功
            String resp = recvMsg();
            if ("success".equals(resp)) {
                //文件接收的善后工作
                file.setUpdate_time(new Date());
                file.setLastIp(socket.getInetAddress().toString());
                file.setCounts(file.getCounts() - 1);
            }
        } catch (FileNotFoundException e) {
            sendMsg("文件已过期");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
